package com.whitehatsec.sentineldataexchange;

import com.whitehatsec.sentineldataexchange.model.WhiteHatSite;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.SAXException;

/**
 * Repository of site information registered to a specified API key
 *
 * @author August Detlefsen [augustd@codemagi.com]
 */
public class WhiteHatSiteLibrary {

	// the library of sites is stored in a hashmap with the siteID as the key
	// and a site object as the value.
	private HashMap<String, WhiteHatSite> sites = null;
	private String whSiteAPI_URL = null;
	private boolean verbose = false;

	// Constructor Loads List of Sites
	public WhiteHatSiteLibrary(Properties props) {
		this.whSiteAPI_URL = props.getProperty("WHITEHAT_SITE_API_URL");
		this.verbose = (props.getProperty("VERBOSE_REPORTING").equalsIgnoreCase("TRUE"));
	}

	public WhiteHatSite getSite(String siteID) {
		return sites.get(siteID);
	}

	public int getNumberOfSites() {
		return sites.size();
	}
	
	public List<WhiteHatSite> getSites() {
	    return new ArrayList(sites.values());
	}

	/**
	 * Connect to the WhiteHat Sentinel Site API
	 * Retrieve the list of sites associated with key
	 * Parse the Site XML and populate the list of sites.
	 * NOT: then connect to the Site API and retrieve each site's details
	 */
	public void loadSites(SentinelLogin login) {
		// retrieve and parse the site XML
		if (verbose) {
			System.out.println("Attempting to connect to the Sentinel Site API at " + this.whSiteAPI_URL);
		}

		InputStream sitesXML = Utils.getUrlAsStream(whSiteAPI_URL, null, login.getCookies());

		sites = parseDocument(sitesXML);
		if (verbose) {
			System.out.println( this.getNumberOfSites() + " sites retrieved.");
		}

		// Iterate through the list of sites and call the API to load the site details
		/*
		if (verbose) {
			System.out.println("Attempting to retrieve the details for " + this.getNumberOfSites() + " sites.");
		}
		for (WhiteHatSite theSite : sites.values()) {
			loadSiteDetails(theSite, login);
		}
		if (verbose) {
			System.out.println("Successfully retrieved the details for " + this.getNumberOfSites() + " sites.");
		}
		 */
	}

	/**
	 * Load a given site's details
	 */
	private void loadSiteDetails(SentinelLogin login, WhiteHatSite whSite) {
		InputStream detailsXML = Utils.getUrlAsStream(this.whSiteAPI_URL + whSite.getSiteID(), null, login.getCookies());
		whSite = parseDetails(detailsXML);
	}

	/**
	 * Load a given site's details
	 */
	public WhiteHatSite loadSiteDetails(SentinelLogin login, Integer siteID) {
		InputStream detailsXML = Utils.getUrlAsStream(this.whSiteAPI_URL + siteID, null, login.getCookies());
		return parseDetails(detailsXML);
	}

	/**
	 * Retrieve and Parse WhiteHat Sentinel Site API XML
	 */
	public HashMap<String, WhiteHatSite> parseDocument(InputStream xml) {
		// create a new site library handler
		WhiteHatSiteListLoader whSiteListLoader = new WhiteHatSiteListLoader();

		// create a SAXParser factory
		System.setProperty("javax.xml.parsers.SAXParserFactory", "org.apache.xerces.jaxp.SAXParserFactoryImpl");
		SAXParserFactory spf = SAXParserFactory.newInstance();

		try {
			// create a new instance of parser
			SAXParser siteSaxParser = spf.newSAXParser();

			// parse the file and register the library handler
			siteSaxParser.parse(xml, whSiteListLoader);

		} catch (SAXException se) {
			se.printStackTrace(System.err);
		} catch (ParserConfigurationException pce) {
			pce.printStackTrace(System.err);
		} catch (IOException ie) {
			System.err.println("Problem connecting to the WhiteHat Sentinel Site API");
		} finally {
			Utils.closeStream(xml);
		}

		// return the populated site library
		return whSiteListLoader.getSites();
	}

		/**
	 * Retrieve and Parse WhiteHat Sentinel Site API XML
	 */
	public WhiteHatSite parseDetails(InputStream xml) {
		// create a new site detail handler
		WhiteHatSiteDetailLoader whSiteDetailLoader = new WhiteHatSiteDetailLoader();

		// create a SAXParser factory
		System.setProperty("javax.xml.parsers.SAXParserFactory", "org.apache.xerces.jaxp.SAXParserFactoryImpl");
		SAXParserFactory spf = SAXParserFactory.newInstance();

		try {
			// create a new instance of parser
			SAXParser siteSaxParser = spf.newSAXParser();

			// parse the file and register the library handler
			siteSaxParser.parse(xml, whSiteDetailLoader);

		} catch (SAXException se) {
			se.printStackTrace(System.err);
		} catch (ParserConfigurationException pce) {
			pce.printStackTrace(System.err);
		} catch (IOException ie) {
			ie.printStackTrace(System.err);
		} finally {
			Utils.closeStream(xml);
		}

		// return the populated site library
		return whSiteDetailLoader.getSite();
	}
}
